# 描述符号只能应用于类属性
# 如果直接用在对象的属性上，魔法就会失灵

class Descriptor:

    def __get__(self, instance, owner):
        print("get~")


class C:

    def __init__(self):
        # 如果直接用在对象的属性上，魔法就会失灵
        self.x = Descriptor()


c = C()
print(c.x)
# <__main__.DFail object at 0x1030a2850>


print("=====" * 20)


class D:
    # 描述符号只能应用于类属性
    x = Descriptor()


d = D()
print(d.x)
# get~


print("数据描述符" * 20)

# 如果实现了 __set__() 或者 __delete__() 方法就是数据描述符号

# 如果只实现了 __get__()  方法就是非数据描述符号
# 为什么要区分呢？因为当发生属性访问的时候，他们的优先级别是不一样的，从高到低如下：
# 数据描述符
# 实例对象属性
# 非数据描述符
# 类属性


d.x = 'FishC'
print(d.x)  # FishC,没有被拦截了
# 使用类名去符号还是可以的被拦截的
D.x  # get~,只是对象d的x属性被覆盖了

print("=====" * 20)


class EeHandle:
    def __get__(self, instance, owner):
        print("get~")

    def __set__(self, instance, value):
        print("set~")


class Ee:
    x = EeHandle()


ee = Ee()
ee.x  # get~
ee.x = "FishC"  # set~
ee.x  # get~
print(ee.__dict__)  # {} 上面的赋值操作没有生效，因为他被数据描述符拦截了

# 直接赋值
ee.__dict__['x'] = 'FishC'
print(ee.__dict__)  # {'x': 'FishC'}
# 看看能不能访问
ee.x  # get~ 依然被描述符拦截了

print("=====" * 20)


class Ff:
    x = EeHandle()

    def __getattribute__(self, name):
        # 该方法的优先级在数据描述符之前
        print("aha~")


ff = Ff()
ff.x  # aha~
